#ifndef SOCKS5_DEF_H
#define SOCKS5_DEF_H
#pragma once

#include <cstdint>

#define S5_TIME_OUT                     30000
#define S5_VERSION_PROTOCOL             0x05
#define S5_VERSION_AUTHENTICATION       0x01
#define S5_METHOD_NO_AUTHENTICATION     0x00
#define S5_METHOD_USERNAME_PASSWORD     0x02
#define S5_METHOD_NO_ACCEPTABLE         0xff
#define S5_STATUS_SUCCESS               0x00
#define S5_STATUS_FAILURE               0xff
#define S5_CMD_CONNECT                  0x01
#define S5_CMD_BIND                     0x02
#define S5_CMD_UDP_ASSOCIATE            0x03
#define S5_RSV                          0x00
#define S5_FRAG_STAND_ALONE             0x00
#define S5_ATYP_IPV4                    0x01
#define S5_ATYP_DOMAINNAME              0x03
#define S5_REP_SUCCEEDED                0x00
#define S5_REP_GENERAL_SERVER_FAILURE   0x01
#define S5_REP_CONNECTION_NOT_ALLOWED   0x02
#define S5_REP_NETWORK_UNREACHABLE      0x03
#define S5_REP_HOST_UNREACHABLE         0x04
#define S5_REP_CONNECTION_REFUSED       0x05
#define S5_REP_TTL_EXPIRED              0x06
#define S5_REP_COMMAND_NOT_SUPPORTED    0x07
#define S5_REP_ADDRESS_NOT_SUPPORTED    0x08

#pragma pack(push, 1)

struct MethodAck {
    MethodAck() : ver(S5_VERSION_PROTOCOL), method(S5_METHOD_NO_ACCEPTABLE) {}
    uint8_t     ver;
    uint8_t     method;
};

struct AuthenticationAck {
    AuthenticationAck() : ver(S5_VERSION_AUTHENTICATION), status(S5_STATUS_FAILURE) {}
    uint8_t     ver;
    uint8_t     status;
};

struct RequestAck {
    RequestAck() : ver(S5_VERSION_PROTOCOL), rsv(S5_RSV), atyp(S5_ATYP_IPV4), bnd_addr(0), bnd_port(0) {}
    uint8_t     ver;
    uint8_t     rep;
    uint8_t     rsv;
    uint8_t     atyp;
    u_long      bnd_addr;
    u_short     bnd_port;
};

struct UdpHeaderPrefix {
    uint16_t    rsv;
    uint8_t     frag;
    uint8_t     atyp;
};

struct UdpHeader {
    UdpHeader() : rsv(S5_RSV), frag(S5_FRAG_STAND_ALONE), atyp(S5_ATYP_IPV4) {}
    uint16_t    rsv;
    uint8_t     frag;
    uint8_t     atyp;
    u_long      dst_addr;
    u_short     dst_port;
};

#pragma pack(pop)

#endif // SOCKS5_DEF_H